package ihm;

import java.awt.ComponentOrientation;
import java.awt.FlowLayout;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;

import org.janusproject.kernel.address.AgentAddress;
import org.janusproject.kernel.agent.Kernel;
import org.janusproject.kernel.agent.Kernels;
import org.janusproject.kernel.channels.ChannelInteractable;

import sma.agents.channels.GoalChannel;
import sma.agents.listeners.MoveGoalListener;
import sma.agents.listeners.MoveListener;
import sma.organizations.roles.Goal;

import appli.Launcher;
import appli.SmaLauncher;
import appli.Telemeter;
import appli.utils.Config;
import appli.utils.MoveEnum;

/**
 * Frame de l'application. Pour l'instant elle ne contient qu'un seul JPanel.
 * Depuis la v0.2 il n'y a plus de KeyListener transmis au GoalAgent, nous utilisons maintenant les channel de Janus
 * Depuis la v0.4 Nous lan�ons plusieurs LayeredPane, pour repr�senter plusieurs t�l�m�tres et l'agent de D�cision
 * 
 * @author Etienne
 * @version 0.4
 */
public class AppliWindow extends JFrame implements KeyListener, MouseListener {
	/**
	 * Multiagent system panel drawing
	 */
	private List<TelemetrePanel> telemetrePanels = new ArrayList<TelemetrePanel>();
	
	private JPanel config;
	
	private ConfigSmaPanel configSMA;
	
	//private JFrame frame;
	
	private SmaPanel smaPanel;
	
	/**
	 * goalChannel list
	 */
	private List<GoalChannel> listGoalChannel = new ArrayList<GoalChannel>();
	
	private Launcher launcher;
	
	private appli.SmaLauncher sma;
	
	private FlowLayout experimentLayout = new FlowLayout();
	
	private JPanel compsToExperiment = new JPanel();
	

	/**
	 * Constructor and only method of this class
	 * Create the frame and adding a jpanel
	 * 
	 * @param _launcher le Launcher de l'application
	 */
	public AppliWindow(Launcher _launcher) {
		super();
		launcher = _launcher;
		
		//Create frame
		//frame = new JFrame();
		this.setFocusable(true);
		
		compsToExperiment.setLayout(experimentLayout);
        experimentLayout.setAlignment(FlowLayout.TRAILING);
        
      //Left to right component orientation is selected by default
        compsToExperiment.setComponentOrientation(
                ComponentOrientation.LEFT_TO_RIGHT);
     
		//Calcul de la hauteur de la fen�tre :
        this.setSize(Config.PANEL_SIZE * 2 + Config.PANEL_CONFIG_SMA_SIZE, Config.PANEL_SIZE);
        this.setTitle("Simulation Panel");
        this.setResizable(false);
        this.setLocationRelativeTo(null);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		//Allow showing window
        this.setVisible(true);
		
		loadConfigPanel();
	}
		
	/**
	 * Affiche les panels concernant le SMA
	 */
	public void loadSmaPanels(){
		
		compsToExperiment.remove(config);
		
		configSMA.switchToParkMode();
		
		//Calcul de la hauteur de la fen�tre :
		int height = 140 + appli.Launcher.listTelemeters.size() * Config.PANEL_SIZE;
		
		this.setSize(Config.PANEL_SIZE * 2 + Config.PANEL_CONFIG_SMA_SIZE, height);
		
		//Add VoiturePanel :
		smaPanel = new SmaPanel(Config.PANEL_SIZE*2, height);
		
		//Ajout du t�l�m�tre avant :
		telemetrePanels.add(new TelemetrePanel(new Point(), Launcher.listTelemeters.get(0).getPort()));
		telemetrePanels.add(new TelemetrePanel(new Point(0 , Config.PANEL_SIZE + 140),Launcher.listTelemeters.get(1).getPort()));
		
		//smaPanel.addTelemeterPanel(telemetrePanels.get(0));
		//smaPanel.addTelemeterPanel(telemetrePanels.get(1));
		
		Iterator<TelemetrePanel> it = telemetrePanels.iterator();
		int  i = 0;
		while(it.hasNext()) 
		{
			TelemetrePanel tmpPanel = it.next();
			//frame.add(tmpPanel);
			smaPanel.addTelemeterPanel(tmpPanel);
			this.listGoalChannel.add(sma.getGoalAgent(i).getChannelImpl());
			i++;
		}
		
		smaPanel.buildVoiturePanel();
			
				
		compsToExperiment.add(smaPanel);
	
		//Refresh the frame
		compsToExperiment.repaint();
		
		//Catch key events
		this.addKeyListener(this);
		this.addMouseListener(this);
		this.requestFocus();
	}
	

	private void loadConfigPanel(){
		
		configSMA = new ConfigSmaPanel(this);
		compsToExperiment.add(configSMA);
		
		config = new ConfigPanel(this, configSMA);
		compsToExperiment.add(config);
		
		this.getContentPane().add(compsToExperiment);
		
		this.pack();
		this.validate();
		this.repaint();
	}
	
	/**
	 * Lance la simulation
	 */
	public void startSimu(){
		launcher.startSimu();
	}
	
	
	/**
	 * @return agents panel
	 * @param i L'identifiant du panel télémètre que l'on veut récupérer
	 */
	public JComponent getAgents(int i) {
		return telemetrePanels.get(i);
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}
	
	public void keyPressed(KeyEvent e) {
		//Move goal 1 :
		if (e.getKeyCode() == KeyEvent.VK_UP)
			this.listGoalChannel.get(0).moveGoal(Launcher.listTelemeters.get(0).getPort(), MoveEnum.UP);
		else if (e.getKeyCode() == KeyEvent.VK_DOWN)
			this.listGoalChannel.get(0).moveGoal(Launcher.listTelemeters.get(0).getPort(), MoveEnum.DOWN);
		else if (e.getKeyCode() == KeyEvent.VK_LEFT)
			this.listGoalChannel.get(0).moveGoal(Launcher.listTelemeters.get(0).getPort(), MoveEnum.LEFT);
		else if (e.getKeyCode() == KeyEvent.VK_RIGHT)
			this.listGoalChannel.get(0).moveGoal(Launcher.listTelemeters.get(0).getPort(), MoveEnum.RIGHT);
		
		//Move goal 2 :
		if (e.getKeyCode() == KeyEvent.VK_Z)
			this.listGoalChannel.get(1).moveGoal(Launcher.listTelemeters.get(1).getPort(), MoveEnum.UP);
		else if (e.getKeyCode() == KeyEvent.VK_S)
			this.listGoalChannel.get(1).moveGoal(Launcher.listTelemeters.get(1).getPort(), MoveEnum.DOWN);
		else if (e.getKeyCode() == KeyEvent.VK_Q)
			this.listGoalChannel.get(1).moveGoal(Launcher.listTelemeters.get(1).getPort(), MoveEnum.LEFT);
		else if (e.getKeyCode() == KeyEvent.VK_D)
			this.listGoalChannel.get(1).moveGoal(Launcher.listTelemeters.get(1).getPort(), MoveEnum.RIGHT);
		
		//Want to park ?
		if(e.getKeyCode() == KeyEvent.VK_SPACE){
				sma.stopDecisiveAgents();

			}
			
		if(e.getKeyCode() == KeyEvent.VK_ENTER){
			if(Config.PARK_MODE){
				
				Config.PARK_MODE = false;
				configSMA.switchToParkMode();
				Config.SMA_CONSTANTE = configSMA.getConstantes(Config.PARK_MODE);
				sma.launchDecisiveAgents(this);
			}else{
				Config.PARK_MODE = true;
				Config.SMA_CONSTANTE_PARK = configSMA.getConstantes(Config.PARK_MODE);
				configSMA.switchToParkMode();
				sma.launchDecisiveAgents(this);
			}
		}
	}

	/**
	 * Set the SMA 
	 * @param _sma the sma
	 */
	public void setSma(SmaLauncher _sma) {
		sma = _sma;
	}

	/**
	 * @return MassCenterPanel
	 */
	public MassCenterPanel getMassCenterPanel() {
		
		return smaPanel.getMassCenterPanel();
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		System.out.println("click !");
		this.requestFocus();
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		System.out.println("pressed !");
		this.requestFocus();
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
}